//----------------------------------*-C++-*----------------------------------//
/*!
 * \file   SlabtranElement.hh
 * \author Jeremy Roberts
 * \date   05/25/2010
 * \brief  A class for handling input for diff2d problems.
 * \note   Copyright (C) 2011 Jeremy Roberts
 */
//---------------------------------------------------------------------------//
// $Rev::                                               $:Rev of last commit
// $Author::                                            $:Author of last commit
// $Date::                                              $:Date of last commit
//---------------------------------------------------------------------------//

#ifndef SLABTRANELEMENT_HH
#define SLABTRANELEMENT_HH

#include <iostream>
#include <algorithm>
#include <numeric>
#include <vector>
#include <iterator>
#include <string>
#include "../utilities/SP.hh"
#include "../utilities/Vector_Lite.hh"
#include "tran/Definitions.hh"

namespace slabtran
{


//===========================================================================//
/*
 * \class SlabtranElement
 * \brief This class hold element data, e.g. geometry and source definitions.
 *
 *  To be added.
 *
 */
//==
class SlabtranElement
{

  public:

    //@{
    //! Useful typedefs for classes that use SlabtranElement
    //@{
	typedef util::SP<SlabtranElement>									  SP_element;
    typedef std::vector<std::vector<std::vector<std::vector<double> > > > Vec_4_d;
    typedef std::vector<std::vector<std::vector<double> > >               Vec_3_d;
    typedef std::vector<std::vector<double> >                             Vec_2_d;
    typedef std::vector<double>                                           Vec_1_d;
    typedef std::vector<std::vector<std::vector<int> > >                  Vec_3_i;
    typedef std::vector<std::vector<int> >                                Vec_2_i;
    typedef std::vector<int>                                              Vec_1_i;
    //@}

  private:

		/// \brief store my dimension
        int N;

        /// \brief my identification number (numbering in order of read)
        int d_id;

        /// \brief my description
        std::string d_desc;

        /// \brief volumetric source by coarse mesh and group [x][y][z][g]
        Vec_4_d d_src;

        /// \brief material placement by coarse mesh [dim][mtid]
        Vec_3_i d_mt; // a mat id at [i][j][k]

        /// \brief number of coarse meshes in each direction [dim]
        Vec_1_i  d_ncm;

        /// \brief coarse mesh edges [dim][edge]
        Vec_2_d  d_cm;

        /// \brief number of fine meshes per coarse mesh [dim][number]
        Vec_2_i  d_nfm;

        /// \brief boundary conditions  (0=vacuum, 1=reflect, 2=inc cur)
        Vec_1_i d_bc;

        /// \brief symmetry ( 0=none, 1=full symmetry )
        int sym;

        //----------------------------------------------------------------------
        // Add stuff

  public:

        // Constructor.
        SlabtranElement(){};

		// Destructor.
        ~SlabtranElement(){};

        //----------------------------------------------------------------------
        // Return stuff

        // Return my identification
        int id(){ return d_id; };

        // Return my description
        std::string desc(){ return d_desc; };

        // Return source
        double src(int i, int j, int k, int g){ return d_src[i][j][k][g]; };

        // Return material placement
        int mt(int i, int j = 0, int k = 0){ return d_mt[i][j][k]; };

        // Return coarse mesh count in in x/y/z
        int ncm(int dim){ return d_ncm[dim]; };

        // Return coarse mesh edge in in x/y/z
        double cm(int xyz, int ijk){ return d_cm[xyz][ijk]; };

        // Return fine mesh count in x/y/z
        int nfm(int xyz, int ijk){ return d_nfm[xyz][ijk]; };

        // Return total fine mesh count in x/y/z
        int nfm(int xyz){ return std::accumulate( d_nfm[xyz].begin(), d_nfm[xyz].end(), 0); };

        // return fine mesh vector
//        vector<int> nfm(int xyz) const
//        {
//        	int poo =  std::accumulate( d_nfm[I].begin(), d_nfm[I].end(), 0);
//        	std::cout << " poo = " << poo << std::endl;
//        	return d_nfm[xyz];
//        };


        // let input routines fill out the data; we're just a container
        friend class SlabtranInput; 

};

} // end namespace slabtran

#endif // SLABTRANELEMENT_HH

//---------------------------------------------------------------------------//
//                 end of SlabtranElement.hh
//---------------------------------------------------------------------------//

